﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace Milkify.Input
{
    [System.Windows.Markup.ContentProperty("Gestures")]
    public class MultipleInputGesture : InputGesture
    {
        private int mNextIdToMatch;

        public InputGestureCollection Gestures { get; private set; }

        public event EventHandler<MultipleInputGestureEventArgs> GestureMatched;

        public MultipleInputGesture()
        {
            mNextIdToMatch = 0;
            Gestures = new InputGestureCollection();
        }

        public MultipleInputGesture(IEnumerable<InputGesture> gestures)
            : this()
        {
            foreach (var gesture in gestures)
            {
                Gestures.Add(gesture);
            }
        }

        public void ResetMatching()
        {
            mNextIdToMatch = 0;
        }

        public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
        {
            KeyEventArgs keyEventArgs = inputEventArgs as KeyEventArgs;
            if (keyEventArgs == null)
                return false;
            if (keyEventArgs.IsRepeat)
                return false;

            if (keyEventArgs.Key == Key.Escape && mNextIdToMatch > 0)
            {
                var eventArgs = new MultipleInputGestureEventArgs(mNextIdToMatch, GestureMatchType.Failed, keyEventArgs);
                OnGestureMatched(eventArgs);
                mNextIdToMatch = 0;
                return false;
            }
            
            if (Gestures[mNextIdToMatch].Matches(targetElement, keyEventArgs))
            {
                if (mNextIdToMatch >= Gestures.Count - 1)
                {
                    var eventArgs = new MultipleInputGestureEventArgs(mNextIdToMatch, GestureMatchType.Complete, keyEventArgs);
                    OnGestureMatched(eventArgs);
                    mNextIdToMatch = 0;
                    if (eventArgs.CancelMatch)
                        return false;
                    return true;
                }
                else
                {
                    var eventArgs = new MultipleInputGestureEventArgs(mNextIdToMatch, GestureMatchType.Intermediate, keyEventArgs);
                    OnGestureMatched(eventArgs);
                    if (eventArgs.CancelMatch)
                        mNextIdToMatch = 0;
                    else
                        mNextIdToMatch++;
                    return false;
                }
            }
            else if(mNextIdToMatch > 0)
            {
                var eventArgs = new MultipleInputGestureEventArgs(mNextIdToMatch, GestureMatchType.Failed, keyEventArgs);
                OnGestureMatched(eventArgs);
                mNextIdToMatch = 0;
                return false;
            }

            return false;
        }

        private void OnGestureMatched(MultipleInputGestureEventArgs e)
        {
            if (GestureMatched != null)
                GestureMatched(this, e);
        }
    }
}
